package org.boulderfoodrescue.webapp.server.pickups;

import java.util.LinkedList;
import java.util.List;
import java.util.logging.Logger;

import org.boulderfoodrescue.webapp.server.location.LocationDatabase;
import org.boulderfoodrescue.webapp.server.timeSlots.OneTimeEventDatabase;
import org.boulderfoodrescue.webapp.server.timeSlots.RecurringEventDatabase;
import org.boulderfoodrescue.webapp.server.users.UserAccountsDatabase;
import org.boulderfoodrescue.webapp.shared.Location;
import org.boulderfoodrescue.webapp.shared.OneTimeEvent;
import org.boulderfoodrescue.webapp.shared.Pickup;
import org.boulderfoodrescue.webapp.shared.RecurringEvent;
import org.boulderfoodrescue.webapp.shared.UserAccountDetails;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;


public class PickupDatabase {
	private static final Logger log = Logger.getLogger(PickupDatabase.class.getName());

	public static Long addPickup(Pickup pickup){
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		Entity entity = pickupToEntity(pickup);
		Long key = datastore.put(entity).getId();
		log.info("Added new pickup to datastore: "+pickup.getDatabaseKey());
		return key;
	}

	public static Long updatePickup(Pickup pickup) {
		Long key = null;
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		key =  datastore.put(pickupToEntity(pickup)).getId();
		return key;
	}

	public static List<Pickup> getPickups(int maxToReturn){
		Query query = new Query("pickup");
		return queryPickupDatabse(query, maxToReturn);
	}

	public static List<Pickup> getPickupsOneTimeEvent(Long oneTimeEventKey){
		Query dQuery = new Query("pickup");
		dQuery.addFilter("oneTimeEventDropOffKey", FilterOperator.EQUAL, oneTimeEventKey);
		List<Pickup> dList = queryPickupDatabse(dQuery, 1000);

		Query pQuery = new Query("pickup");
		pQuery.addFilter("oneTimeEventPickupKey", FilterOperator.EQUAL, oneTimeEventKey);
		List<Pickup> pList = queryPickupDatabse(pQuery, 1000);

		List<Pickup> list = new LinkedList<Pickup>(dList);
		list.addAll(pList);
		return list;
	}

	public static List<Pickup> getPickupsRecurringEvent(Long recurringEventKey){
		Query dQuery = new Query("pickup");
		dQuery.addFilter("recurringEventDropOffKey", FilterOperator.EQUAL, recurringEventKey);
		List<Pickup> dList = queryPickupDatabse(dQuery, 1000);

		Query pQuery = new Query("pickup");
		pQuery.addFilter("recurringEventPickupKey", FilterOperator.EQUAL, recurringEventKey);
		List<Pickup> pList = queryPickupDatabse(pQuery, 1000);

		List<Pickup> list = new LinkedList<Pickup>(dList);
		list.addAll(pList);
		return list;
	}

	private static List<Pickup> queryPickupDatabse(Query query, int maxToReturn){
		List<Pickup> pickups = new LinkedList<Pickup>();
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		List<Entity> dPickups = datastore.prepare(query).asList(FetchOptions.Builder.withLimit(maxToReturn));
		if(dPickups.size() == maxToReturn)
			log.warning("There are more than the max number of pickups in the database");
		for(Entity dPickup : dPickups){
			Pickup pickup = entityToPickup(dPickup);
			pickups.add(pickup);
		}
		return pickups;
	}


	public static void removePickup(Pickup pickup) {
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		Entity databaseUser = new Entity("pickup", pickup.getDatabaseKey());
		datastore.delete(databaseUser.getKey());
		log.info("Deleted user: "+pickup.getDatabaseKey());
	}

	private static Pickup entityToPickup(Entity dPickup)
	{
		Pickup pickup = new Pickup();

		pickup.setDonorKey((Long) dPickup.getProperty("donorKey"));
		Location donor = LocationDatabase.getLocation(pickup.getDonorKey(), true);
		pickup.setDonor(donor);
		pickup.setNotes((String) dPickup.getProperty("notes"));
		pickup.setOneTimeEventDropOffKey((Long) dPickup.getProperty("oneTimeEventDropOffKey"));
		if(pickup.getOneTimeEventDropOffKey() != null){
			OneTimeEvent oneTimeEvent = OneTimeEventDatabase.getOneTimeEvent(pickup.getOneTimeEventDropOffKey());
			pickup.setOneTimeEventDropOff(oneTimeEvent);
		}
		pickup.setRecurringEventDropOffKey((Long) dPickup.getProperty("recurringEventDropOffKey"));
		if(pickup.getRecurringEventDropOffKey() != null){
			RecurringEvent recurringEvent = RecurringEventDatabase.getRecurringEvent(pickup.getRecurringEventDropOffKey());
			pickup.setRecurringEventDropOff(recurringEvent);
		}
		pickup.setOneTimeEventPickupKey((Long) dPickup.getProperty("oneTimeEventPickupKey"));
		if(pickup.getOneTimeEventPickupKey() != null){
			OneTimeEvent oneTimeEvent = OneTimeEventDatabase.getOneTimeEvent(pickup.getOneTimeEventPickupKey());
			pickup.setOneTimeEventPickup(oneTimeEvent);
		}
		pickup.setRecurringEventPickupKey((Long) dPickup.getProperty("recurringEventPickupKey"));
		if(pickup.getRecurringEventPickupKey() != null){
			RecurringEvent recurringEvent = RecurringEventDatabase.getRecurringEvent(pickup.getRecurringEventPickupKey());
			pickup.setRecurringEventPickup(recurringEvent);
		}
		pickup.setRecipientKey((Long) dPickup.getProperty("recipientKey"));
		if(pickup.getRecipientKey() != null){
			Location recipient = LocationDatabase.getLocation(pickup.getRecipientKey(), false);
			pickup.setRecipient(recipient);
		}
		pickup.setRecurring((Boolean) dPickup.getProperty("recurring"));
		pickup.setTransportationViaLong((Long) dPickup.getProperty("transportation"));
		pickup.setVolunteerKey((Long) dPickup.getProperty("volunteerKey"));
		if(pickup.getVolunteerKey() != null){
			UserAccountDetails volunteer = UserAccountsDatabase.getUser(pickup.getVolunteerKey());
			pickup.setVolunteer(volunteer);
		}
		pickup.setDatabaseKey(dPickup.getKey().getId());
		return pickup;
	}

	private static Entity pickupToEntity(Pickup pickup)
	{
		Entity databasePickup;
		if(pickup.getDatabaseKey() != null && pickup.getDatabaseKey() != 0)
			databasePickup = new Entity("pickup", pickup.getDatabaseKey());
		else
			databasePickup = new Entity("pickup");
		databasePickup.setProperty("donorKey", pickup.getDonorKey());
		databasePickup.setProperty("notes", pickup.getNotes());
		databasePickup.setProperty("recipientKey", pickup.getRecipientKey());
		databasePickup.setProperty("recurring", pickup.getRecurring());
		databasePickup.setProperty("oneTimeEventDropOffKey", pickup.getOneTimeEventDropOffKey());
		databasePickup.setProperty("recurringEventDropOffKey", pickup.getRecurringEventDropOffKey());
		databasePickup.setProperty("oneTimeEventPickupKey", pickup.getOneTimeEventPickupKey());
		databasePickup.setProperty("recurringEventPickupKey", pickup.getRecurringEventPickupKey());
		databasePickup.setProperty("transportation", pickup.getTransportationAsLong());
		databasePickup.setProperty("volunteerKey", pickup.getVolunteerKey());
		return databasePickup;
	}
}
